Overview of tutorial
This tutorial simulates a population effect size of Cohen’s d = 0.5
for different sample sizes, and examines the relationship between
Cohen’s d, its 95% Confidence Interval, and the significance of the
t-test’s p-value.
By the end of this lesson you should understand that
p-values are re-expressions of the same information conveyed by
Confidence Intervals, and that statistical power is a re-expression of
the width of Confidence Intervals.
Dependencies
library(tidyr)
library(dplyr)
library(purrr)
library(stringr)
library(forcats)
library(ggplot2)
library(scales)
library(patchwork)
library(knitr)
library(kableExtra)
library(janitor)
library(effsize)
Simulation
# functions for simulation
generate_data <- function(n_per_condition,
mean_control,
mean_intervention,
sd) {
data_control <-
tibble(condition = "control",
score = rnorm(n = n_per_condition, mean = mean_control, sd = sd))
data_intervention <-
tibble(condition = "intervention",
score = rnorm(n = n_per_condition, mean = mean_intervention, sd = sd))
data_combined <- bind_rows(data_control,
data_intervention) |>
mutate(condition = fct_relevel(condition, "intervention", "control"))
return(data_combined)
}
analyze <- function(data) {
res_t_test <- t.test(formula = score ~ condition,
data = data,
var.equal = TRUE,
alternative = "two.sided")
res_cohens_d <- effsize::cohen.d(formula = score ~ condition,
data = data,
pooled = TRUE)
res <- tibble(p = res_t_test$p.value,
cohens_d = res_cohens_d$estimate,
cohens_d_ci_lower = res_cohens_d$conf.int[1],
cohens_d_ci_upper = res_cohens_d$conf.int[2])
return(res)
}
# set seed
set.seed(42)
# simulation parameters
experiment_parameters <- expand_grid(
n_per_condition = seq(from = 10, to = 90, by = 10),
mean_control = 0,
mean_intervention = 0.5,
sd = 1,
iteration = 1:1000
)
# run simulation
simulation <- experiment_parameters |>
mutate(generated_data = pmap(list(n_per_condition,
mean_control,
mean_intervention,
sd),
generate_data)) |>
mutate(results = pmap(list(generated_data),
analyze))
Cohen’s d by sample size
# wrangle
simulation |>
unnest(results) |>
# plot
ggplot(aes(n_per_condition*2, cohens_d)) +
geom_jitter(alpha = 0.25) +
geom_hline(yintercept = 0, linetype = "dotted") +
scale_x_continuous(breaks = breaks_pretty(n = 10),
name = "Total N") +
scale_y_continuous(breaks = breaks_pretty(n = 10),
#limits = c(0,1),
name = "Cohen's d") +
theme_linedraw() +
scale_color_viridis_d(begin = 0.3, end = 0.7) +
ggtitle("Population Cohen's d = 0.5")

- Each point is a Cohen’s d from one dataset (i.e., one
iteration).
- The population Cohen’s d is 0.5. Notice how the distribution of
sample Cohen’s d values vary by sample size: Cohen’s d values above 2.0
and below -0.5 are observed when sample size is very small. As sample
size gets larger, they stabilize. However, individual datasets still
generate Cohen’s d values that diverge substantially from the true value
of 0.5.
Ordered by statistical significance
Let’s color the Cohen’s ds by their statistical significance.
# wrangle
simulation |>
unnest(results) |>
mutate(significant = p < .05) |>
# plot
ggplot(aes(n_per_condition*2, cohens_d, color = significant)) +
geom_jitter(alpha = 0.25) +
geom_hline(yintercept = 0, linetype = "dotted") +
scale_x_continuous(breaks = breaks_pretty(n = 10),
name = "Total N") +
scale_y_continuous(breaks = breaks_pretty(n = 10),
#limits = c(0,1),
name = "Cohen's d") +
theme_linedraw() +
scale_color_viridis_d(begin = 0.3, end = 0.7, direction = -1) +
ggtitle("Population Cohen's d = 0.5")

- There is clearly a cut-off value for each sample size that
determines when a Cohen’s d value is associated with a significant
vs. non-significant t-test p-value. What determines this cut-off? Do you
have an intuition for it?
Average effect size for significant effects
Quick aside: Significant results are more likely to be published than
non significant ones. If we only look at the significant results, what
is the average effect size by N?
Plot only the significant effect sizes, and add their means.
# wrangle
simulation |>
unnest(results) |>
mutate(significant = p < .05) |>
filter(significant) |>
# plot
ggplot(aes(n_per_condition*2, cohens_d, color = significant)) +
geom_jitter(alpha = 0.25) +
# add mean points
stat_summary(fun = "mean",
geom = "point",
size = 3,
color = "#35608DFF") +
geom_hline(yintercept = 0, linetype = "dotted") +
scale_x_continuous(breaks = breaks_pretty(n = 10),
name = "Total N") +
scale_y_continuous(breaks = breaks_pretty(n = 10),
#limits = c(0,1),
name = "Cohen's d") +
theme_linedraw() +
scale_color_viridis_d(begin = 0.3, end = 0.7, direction = -1) +
ggtitle("Population Cohen's d = 0.5")

- Back to the q: There is clearly a cut-off value for each sample size
that determines when a Cohen’s d value is associated with a significant
vs. non-significant t-test p-value. What determines this cut-off? Do you
have an intuition for it?
Cohen’s d and its 95% CIs
To understand it further, let’s add the 95% Confidence Intervals.
Randomly select one dataset per sample size
To understand the plot, we’ll plot just one data set (iteration) for
each sample size.
Re-run the chunk to select new random values. Notice how the
magnitude of the Cohen’s d values ‘dance’ around between data sets due
to random sampling error, but the width of the Confidence Intervals do
not. Confidence width is steady as it is a function of sample size.
# wrangle
simulation |>
unnest(results) |>
mutate(significant = p < .05) |>
# randomly sample 1 effects size per sample size
group_by(n_per_condition) |>
slice_sample(n = 1) |>
ungroup() |>
# plot
ggplot(aes(n_per_condition*2, cohens_d, color = significant)) +
geom_point() +
# 95% CIs
geom_linerange(aes(ymin = cohens_d_ci_lower, ymax = cohens_d_ci_upper)) +
geom_hline(yintercept = 0, linetype = "dotted") +
scale_x_continuous(breaks = breaks_pretty(n = 10),
name = "Total N") +
scale_y_continuous(breaks = breaks_pretty(n = 10),
#limits = c(0,1),
name = "Cohen's d") +
theme_linedraw() +
scale_color_viridis_d(begin = 0.3, end = 0.7) +
ggtitle("Population Cohen's d = 0.5\nOne randomly selected dataset per sample size")

- Significant when 95% CI excludes zero effect size
All datasets
Now let’s plot all the data sets (iterations).
# wrangle
simulation |>
unnest(results) |>
mutate(significant = p < .05,
total_n = paste("N =", n_per_condition*2),
total_n = fct_reorder(total_n, as.numeric(str_extract(total_n, "\\d+")))) |>
# plot
ggplot(aes(iteration, cohens_d, color = significant)) +
geom_point(alpha = 0.5) +
geom_linerange(aes(ymin = cohens_d_ci_lower, ymax = cohens_d_ci_upper), alpha = 0.2) +
geom_hline(yintercept = 0, linetype = "dotted") +
scale_x_continuous(breaks = breaks_pretty(n = 10),
name = "Iteration") +
scale_y_continuous(breaks = breaks_pretty(n = 10),
#limits = c(0,1),
name = "Cohen's d") +
theme_linedraw() +
scale_color_viridis_d(begin = 0.3, end = 0.7) +
facet_wrap(~ total_n, ncol = 3, scales = "free_y")

Ordered by Cohen’s d
The above plot is hard to understand. Let’s order the Cohen’s ds from
smallest to largest, so the small ones are on the left and the large
ones are on the right.
# wrangle
simulation |>
unnest(results) |>
mutate(significant = p < .05,
total_n = paste("N =", n_per_condition*2),
total_n = fct_reorder(total_n, as.numeric(str_extract(total_n, "\\d+")))) |>
arrange(n_per_condition, cohens_d) |>
group_by(n_per_condition) |>
mutate(rank = row_number()) |>
ungroup() |>
# plot
ggplot(aes(rank, cohens_d, color = significant)) +
geom_point() +
geom_linerange(aes(ymin = cohens_d_ci_lower, ymax = cohens_d_ci_upper), alpha = 0.2) +
geom_hline(yintercept = 0, linetype = "dotted") +
scale_x_continuous(breaks = breaks_pretty(n = 10),
name = "Ranked iteration") +
scale_y_continuous(breaks = breaks_pretty(n = 10),
#limits = c(0,1),
name = "Cohen's d") +
theme_linedraw() +
scale_color_viridis_d(begin = 0.3, end = 0.7) +
facet_wrap(~ total_n, ncol = 3)

- Notice the relationship between 95% CI and p value
significance.
- A certain percentage of Cohen’s ds are green vs. blue. What is this
percentage also called? What statistical property?
Mean Cohen’s d and mean interval width by sample size
Now let’s average over the Cohen’s ds in each condition to find the
mean Cohen’s d and its mean 95% CIs.
# wrangle
simulation_summary <- simulation |>
# unnest results
unnest(results) |>
group_by(n_per_condition) |>
summarize(proportion_significant = mean(p < .05),
mean_cohens_d = mean(cohens_d),
mean_cohens_d_ci_lower = mean(cohens_d_ci_lower),
mean_cohens_d_ci_upper = mean(cohens_d_ci_upper)) |>
mutate(centered_mean_cohens_d_ci_lower = mean_cohens_d_ci_lower - mean_cohens_d,
centered_mean_cohens_d_ci_upper = mean_cohens_d_ci_upper - mean_cohens_d)
# plot results
p1 <- ggplot(simulation_summary, aes(n_per_condition*2, mean_cohens_d)) +
geom_point() +
geom_linerange(aes(ymin = mean_cohens_d_ci_lower, ymax = mean_cohens_d_ci_upper)) +
geom_hline(yintercept = 0, linetype = "dotted") +
scale_x_continuous(breaks = breaks_pretty(n = 10),
name = "Total sample size") +
scale_y_continuous(breaks = breaks_pretty(n = 5),
#limits = c(0,1),
name = "Mean Cohen's d\n(and mean 95% CIs)") +
theme_linedraw() +
ggtitle("Population Cohen's d = 0.5")
p1

Mean Cohen’s d and power by sample size
p2 <- ggplot(simulation_summary, aes(n_per_condition*2, proportion_significant)) +
geom_point() +
geom_hline(yintercept = 0.05, linetype = "dotted") +
geom_hline(yintercept = 0.80, linetype = "dotted") +
scale_x_continuous(breaks = breaks_pretty(n = 10),
name = "Total sample size") +
scale_y_continuous(breaks = breaks_pretty(n = 5),
limits = c(0,1),
name = "Proportion of significant\np-values") +
theme_linedraw()
p1 + p2 + plot_layout(ncol = 1)

Exercise: Power for equivalence test
See Lakens et al., 2018 for a tutorial on the concepts below.
Using a Smallest Effect Size of Interest (SESOI) of Cohen’s d = 0.2,
what is the power of a Two One-Sided Equivalence Test (TOST) for
different sample sizes? What N is needed for 80% power to detect a true
null effect size as equivalent to zero?
Note: because reasons, use the 90% Confidence Interval instead of 95
(see Lakens et al., 2018).
knitr::include_graphics("materials/lakens et al 2018 figure 1.png")

Session info
## R version 4.3.3 (2024-02-29)
## Platform: aarch64-apple-darwin20 (64-bit)
## Running under: macOS 15.4
##
## Matrix products: default
## BLAS: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRblas.0.dylib
## LAPACK: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRlapack.dylib; LAPACK version 3.11.0
##
## locale:
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
##
## time zone: Europe/Zurich
## tzcode source: internal
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] effsize_0.8.1 janitor_2.2.1 kableExtra_1.4.0
## [4] knitr_1.49 patchwork_1.2.0.9000 scales_1.3.0
## [7] ggplot2_3.5.1 forcats_1.0.0 stringr_1.5.1
## [10] purrr_1.0.4 dplyr_1.1.4 tidyr_1.3.1
##
## loaded via a namespace (and not attached):
## [1] gtable_0.3.6 jsonlite_1.8.9 compiler_4.3.3 tidyselect_1.2.1
## [5] xml2_1.3.6 snakecase_0.11.1 jquerylib_0.1.4 png_0.1-8
## [9] systemfonts_1.0.6 yaml_2.3.10 fastmap_1.2.0 R6_2.6.1
## [13] generics_0.1.3 tibble_3.2.1 munsell_0.5.1 lubridate_1.9.4
## [17] svglite_2.1.3 bslib_0.8.0 pillar_1.10.1 rlang_1.1.5
## [21] cachem_1.1.0 stringi_1.8.4 xfun_0.49 sass_0.4.9
## [25] timechange_0.3.0 viridisLite_0.4.2 cli_3.6.4 withr_3.0.2
## [29] magrittr_2.0.3 digest_0.6.37 grid_4.3.3 rstudioapi_0.17.1
## [33] lifecycle_1.0.4 vctrs_0.6.5 evaluate_1.0.1 glue_1.8.0
## [37] farver_2.1.2 colorspace_2.1-1 rmarkdown_2.29 tools_4.3.3
## [41] pkgconfig_2.0.3 htmltools_0.5.8.1
LS0tCnRpdGxlOiAiVW5kZXJzdGFuZGluZyB0aGUgbGluayBiZXR3ZWVuIHAtdmFsdWVzLCBDb25maWRlbmNlIEludGVydmFscywgYW5kIHBvd2VyIgphdXRob3I6ICJJYW4gSHVzc2V5IgpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCAlQiwgJVknKWAiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBoaWdobGlnaHQ6IGhhZGRvY2sKICAgIHRoZW1lOiBmbGF0bHkKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwotLS0KCiMgT3ZlcnZpZXcgb2YgdHV0b3JpYWwKClRoaXMgdHV0b3JpYWwgc2ltdWxhdGVzIGEgcG9wdWxhdGlvbiBlZmZlY3Qgc2l6ZSBvZiBDb2hlbidzIGQgPSAwLjUgZm9yIGRpZmZlcmVudCBzYW1wbGUgc2l6ZXMsIGFuZCBleGFtaW5lcyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gQ29oZW4ncyBkLCBpdHMgOTUlIENvbmZpZGVuY2UgSW50ZXJ2YWwsIGFuZCB0aGUgc2lnbmlmaWNhbmNlIG9mIHRoZSB0LXRlc3QncyAqcCotdmFsdWUuIAoKQnkgdGhlIGVuZCBvZiB0aGlzIGxlc3NvbiB5b3Ugc2hvdWxkIHVuZGVyc3RhbmQgdGhhdCAqcCotdmFsdWVzIGFyZSByZS1leHByZXNzaW9ucyBvZiB0aGUgc2FtZSBpbmZvcm1hdGlvbiBjb252ZXllZCBieSBDb25maWRlbmNlIEludGVydmFscywgYW5kIHRoYXQgc3RhdGlzdGljYWwgcG93ZXIgaXMgYSByZS1leHByZXNzaW9uIG9mIHRoZSB3aWR0aCBvZiBDb25maWRlbmNlIEludGVydmFscy4KCiMgQ2l0YXRpb24gJiBMaWNlbnNlCgpDaXRhdGlvbjogCgpJYW4gSHVzc2V5ICgyMDI0KSBJbXByb3ZpbmcgeW91ciBzdGF0aXN0aWNhbCBpbmZlcmVuY2VzIHRocm91Z2ggc2ltdWxhdGlvbiBzdHVkaWVzIGluIFIuIGh0dHBzOi8vZ2l0aHViLmNvbS9pYW5odXNzZXkvc2ltdWxhdGlvbi1jb3Vyc2UKCkxpY2Vuc2U6IAoKW0NDIEJZIDQuMF0oaHR0cHM6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LzQuMC9kZWVkLmVuKQoKYGBge3IsIGluY2x1ZGU9RkFMU0V9CgojIHNldCBkZWZhdWx0IGNodW5rIG9wdGlvbnMKa25pdHI6Om9wdHNfY2h1bmskc2V0KG1lc3NhZ2UgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGQUxTRSkKCiMgZGlzYWJsZSBzY2llbnRpZmljIG5vdGF0aW9uCm9wdGlvbnMoc2NpcGVuID0gOTk5KSAKCmBgYAoKIyBEZXBlbmRlbmNpZXMKCmBgYHtyfQoKbGlicmFyeSh0aWR5cikKbGlicmFyeShkcGx5cikKbGlicmFyeShwdXJycikgCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeShmb3JjYXRzKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoc2NhbGVzKQpsaWJyYXJ5KHBhdGNod29yaykKbGlicmFyeShrbml0cikKbGlicmFyeShrYWJsZUV4dHJhKQpsaWJyYXJ5KGphbml0b3IpCmxpYnJhcnkoZWZmc2l6ZSkKCmBgYAoKIyBTaW11bGF0aW9uCgpgYGB7cn0KCiMgZnVuY3Rpb25zIGZvciBzaW11bGF0aW9uCmdlbmVyYXRlX2RhdGEgPC0gZnVuY3Rpb24obl9wZXJfY29uZGl0aW9uLAogICAgICAgICAgICAgICAgICAgICAgICAgIG1lYW5fY29udHJvbCwKICAgICAgICAgICAgICAgICAgICAgICAgICBtZWFuX2ludGVydmVudGlvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICBzZCkgewogIAogIGRhdGFfY29udHJvbCA8LSAKICAgIHRpYmJsZShjb25kaXRpb24gPSAiY29udHJvbCIsCiAgICAgICAgICAgc2NvcmUgPSBybm9ybShuID0gbl9wZXJfY29uZGl0aW9uLCBtZWFuID0gbWVhbl9jb250cm9sLCBzZCA9IHNkKSkKICAKICBkYXRhX2ludGVydmVudGlvbiA8LSAKICAgIHRpYmJsZShjb25kaXRpb24gPSAiaW50ZXJ2ZW50aW9uIiwKICAgICAgICAgICBzY29yZSA9IHJub3JtKG4gPSBuX3Blcl9jb25kaXRpb24sIG1lYW4gPSBtZWFuX2ludGVydmVudGlvbiwgc2QgPSBzZCkpCiAgCiAgZGF0YV9jb21iaW5lZCA8LSBiaW5kX3Jvd3MoZGF0YV9jb250cm9sLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGFfaW50ZXJ2ZW50aW9uKSB8PgogICAgbXV0YXRlKGNvbmRpdGlvbiA9IGZjdF9yZWxldmVsKGNvbmRpdGlvbiwgImludGVydmVudGlvbiIsICJjb250cm9sIikpCiAgCiAgcmV0dXJuKGRhdGFfY29tYmluZWQpCn0KCmFuYWx5emUgPC0gZnVuY3Rpb24oZGF0YSkgewoKICByZXNfdF90ZXN0IDwtIHQudGVzdChmb3JtdWxhID0gc2NvcmUgfiBjb25kaXRpb24sIAogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXRhLAogICAgICAgICAgICAgICAgICAgICAgIHZhci5lcXVhbCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIikKICAKICByZXNfY29oZW5zX2QgPC0gZWZmc2l6ZTo6Y29oZW4uZChmb3JtdWxhID0gc2NvcmUgfiBjb25kaXRpb24sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9vbGVkID0gVFJVRSkKICAKICByZXMgPC0gdGliYmxlKHAgPSByZXNfdF90ZXN0JHAudmFsdWUsIAogICAgICAgICAgICAgICAgY29oZW5zX2QgPSByZXNfY29oZW5zX2QkZXN0aW1hdGUsCiAgICAgICAgICAgICAgICBjb2hlbnNfZF9jaV9sb3dlciA9IHJlc19jb2hlbnNfZCRjb25mLmludFsxXSwKICAgICAgICAgICAgICAgIGNvaGVuc19kX2NpX3VwcGVyID0gcmVzX2NvaGVuc19kJGNvbmYuaW50WzJdKQoKICByZXR1cm4ocmVzKQp9CgoKIyBzZXQgc2VlZApzZXQuc2VlZCg0MikKCiMgc2ltdWxhdGlvbiBwYXJhbWV0ZXJzCmV4cGVyaW1lbnRfcGFyYW1ldGVycyA8LSBleHBhbmRfZ3JpZCgKICBuX3Blcl9jb25kaXRpb24gPSBzZXEoZnJvbSA9IDEwLCB0byA9IDkwLCBieSA9IDEwKSwKICBtZWFuX2NvbnRyb2wgPSAwLAogIG1lYW5faW50ZXJ2ZW50aW9uID0gMC41LAogIHNkID0gMSwKICBpdGVyYXRpb24gPSAxOjEwMDAKKSAKCiMgcnVuIHNpbXVsYXRpb24Kc2ltdWxhdGlvbiA8LSBleHBlcmltZW50X3BhcmFtZXRlcnMgfD4KICBtdXRhdGUoZ2VuZXJhdGVkX2RhdGEgPSBwbWFwKGxpc3Qobl9wZXJfY29uZGl0aW9uLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVhbl9jb250cm9sLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWFuX2ludGVydmVudGlvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2QpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VuZXJhdGVfZGF0YSkpIHw+CiAgbXV0YXRlKHJlc3VsdHMgPSBwbWFwKGxpc3QoZ2VuZXJhdGVkX2RhdGEpLAogICAgICAgICAgICAgICAgICAgICAgICBhbmFseXplKSkKCmBgYAoKIyBDb2hlbidzIGQgYnkgc2FtcGxlIHNpemUKCmBgYHtyIGZpZy5oZWlnaHQ9NSwgZmlnLndpZHRoPTZ9CgojIHdyYW5nbGUKc2ltdWxhdGlvbiB8PgogIHVubmVzdChyZXN1bHRzKSB8PgogICMgcGxvdAogIGdncGxvdChhZXMobl9wZXJfY29uZGl0aW9uKjIsIGNvaGVuc19kKSkgKwogIGdlb21faml0dGVyKGFscGhhID0gMC4yNSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gImRvdHRlZCIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYnJlYWtzX3ByZXR0eShuID0gMTApLAogICAgICAgICAgICAgICAgICAgICBuYW1lID0gIlRvdGFsIE4iKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IGJyZWFrc19wcmV0dHkobiA9IDEwKSwKICAgICAgICAgICAgICAgICAgICAgI2xpbWl0cyA9IGMoMCwxKSwKICAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICJDb2hlbidzIGQiKSArCiAgdGhlbWVfbGluZWRyYXcoKSArCiAgc2NhbGVfY29sb3JfdmlyaWRpc19kKGJlZ2luID0gMC4zLCBlbmQgPSAwLjcpICsKICBnZ3RpdGxlKCJQb3B1bGF0aW9uIENvaGVuJ3MgZCA9IDAuNSIpCgpgYGAKCi0gRWFjaCBwb2ludCBpcyBhIENvaGVuJ3MgZCBmcm9tIG9uZSBkYXRhc2V0IChpLmUuLCBvbmUgaXRlcmF0aW9uKS4KLSBUaGUgcG9wdWxhdGlvbiBDb2hlbidzIGQgaXMgMC41LiBOb3RpY2UgaG93IHRoZSBkaXN0cmlidXRpb24gb2Ygc2FtcGxlIENvaGVuJ3MgZCB2YWx1ZXMgdmFyeSBieSBzYW1wbGUgc2l6ZTogQ29oZW4ncyBkIHZhbHVlcyBhYm92ZSAyLjAgYW5kIGJlbG93IC0wLjUgYXJlIG9ic2VydmVkIHdoZW4gc2FtcGxlIHNpemUgaXMgdmVyeSBzbWFsbC4gQXMgc2FtcGxlIHNpemUgZ2V0cyBsYXJnZXIsIHRoZXkgc3RhYmlsaXplLiBIb3dldmVyLCBpbmRpdmlkdWFsIGRhdGFzZXRzIHN0aWxsIGdlbmVyYXRlIENvaGVuJ3MgZCB2YWx1ZXMgdGhhdCBkaXZlcmdlIHN1YnN0YW50aWFsbHkgZnJvbSB0aGUgdHJ1ZSB2YWx1ZSBvZiAwLjUuCgojIyBPcmRlcmVkIGJ5IHN0YXRpc3RpY2FsIHNpZ25pZmljYW5jZQoKTGV0J3MgY29sb3IgdGhlIENvaGVuJ3MgZHMgYnkgdGhlaXIgc3RhdGlzdGljYWwgc2lnbmlmaWNhbmNlLiAKCmBgYHtyIGZpZy5oZWlnaHQ9NSwgZmlnLndpZHRoPTZ9CgojIHdyYW5nbGUKc2ltdWxhdGlvbiB8PgogIHVubmVzdChyZXN1bHRzKSB8PgogIG11dGF0ZShzaWduaWZpY2FudCA9IHAgPCAuMDUpIHw+CiAgIyBwbG90CiAgZ2dwbG90KGFlcyhuX3Blcl9jb25kaXRpb24qMiwgY29oZW5zX2QsIGNvbG9yID0gc2lnbmlmaWNhbnQpKSArCiAgZ2VvbV9qaXR0ZXIoYWxwaGEgPSAwLjI1KSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAiZG90dGVkIikgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBicmVha3NfcHJldHR5KG4gPSAxMCksCiAgICAgICAgICAgICAgICAgICAgIG5hbWUgPSAiVG90YWwgTiIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gYnJlYWtzX3ByZXR0eShuID0gMTApLAogICAgICAgICAgICAgICAgICAgICAjbGltaXRzID0gYygwLDEpLAogICAgICAgICAgICAgICAgICAgICBuYW1lID0gIkNvaGVuJ3MgZCIpICsKICB0aGVtZV9saW5lZHJhdygpICsKICBzY2FsZV9jb2xvcl92aXJpZGlzX2QoYmVnaW4gPSAwLjMsIGVuZCA9IDAuNywgZGlyZWN0aW9uID0gLTEpICsKICBnZ3RpdGxlKCJQb3B1bGF0aW9uIENvaGVuJ3MgZCA9IDAuNSIpCgpgYGAKCi0gVGhlcmUgaXMgY2xlYXJseSBhIGN1dC1vZmYgdmFsdWUgZm9yIGVhY2ggc2FtcGxlIHNpemUgdGhhdCBkZXRlcm1pbmVzIHdoZW4gYSBDb2hlbidzIGQgdmFsdWUgaXMgYXNzb2NpYXRlZCB3aXRoIGEgc2lnbmlmaWNhbnQgdnMuIG5vbi1zaWduaWZpY2FudCB0LXRlc3QgcC12YWx1ZS4gV2hhdCBkZXRlcm1pbmVzIHRoaXMgY3V0LW9mZj8gRG8geW91IGhhdmUgYW4gaW50dWl0aW9uIGZvciBpdD8KCiMjIEF2ZXJhZ2UgZWZmZWN0IHNpemUgZm9yIHNpZ25pZmljYW50IGVmZmVjdHMKClF1aWNrIGFzaWRlOiBTaWduaWZpY2FudCByZXN1bHRzIGFyZSBtb3JlIGxpa2VseSB0byBiZSBwdWJsaXNoZWQgdGhhbiBub24gc2lnbmlmaWNhbnQgb25lcy4gSWYgd2Ugb25seSBsb29rIGF0IHRoZSBzaWduaWZpY2FudCByZXN1bHRzLCB3aGF0IGlzIHRoZSBhdmVyYWdlIGVmZmVjdCBzaXplIGJ5IE4/CgpQbG90IG9ubHkgdGhlIHNpZ25pZmljYW50IGVmZmVjdCBzaXplcywgYW5kIGFkZCB0aGVpciBtZWFucy4KCmBgYHtyIGZpZy5oZWlnaHQ9NSwgZmlnLndpZHRoPTZ9CgojIHdyYW5nbGUKc2ltdWxhdGlvbiB8PgogIHVubmVzdChyZXN1bHRzKSB8PgogIG11dGF0ZShzaWduaWZpY2FudCA9IHAgPCAuMDUpIHw+CiAgZmlsdGVyKHNpZ25pZmljYW50KSB8PgogICMgcGxvdAogIGdncGxvdChhZXMobl9wZXJfY29uZGl0aW9uKjIsIGNvaGVuc19kLCBjb2xvciA9IHNpZ25pZmljYW50KSkgKwogIGdlb21faml0dGVyKGFscGhhID0gMC4yNSkgKwogICMgYWRkIG1lYW4gcG9pbnRzIAogIHN0YXRfc3VtbWFyeShmdW4gPSAibWVhbiIsCiAgICAgICAgICAgICAgIGdlb20gPSAicG9pbnQiLAogICAgICAgICAgICAgICBzaXplID0gMywKICAgICAgICAgICAgICAgY29sb3IgPSAiIzM1NjA4REZGIikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gImRvdHRlZCIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYnJlYWtzX3ByZXR0eShuID0gMTApLAogICAgICAgICAgICAgICAgICAgICBuYW1lID0gIlRvdGFsIE4iKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IGJyZWFrc19wcmV0dHkobiA9IDEwKSwKICAgICAgICAgICAgICAgICAgICAgI2xpbWl0cyA9IGMoMCwxKSwKICAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICJDb2hlbidzIGQiKSArCiAgdGhlbWVfbGluZWRyYXcoKSArCiAgc2NhbGVfY29sb3JfdmlyaWRpc19kKGJlZ2luID0gMC4zLCBlbmQgPSAwLjcsIGRpcmVjdGlvbiA9IC0xKSArCiAgZ2d0aXRsZSgiUG9wdWxhdGlvbiBDb2hlbidzIGQgPSAwLjUiKQoKYGBgCgotIEJhY2sgdG8gdGhlIHE6IFRoZXJlIGlzIGNsZWFybHkgYSBjdXQtb2ZmIHZhbHVlIGZvciBlYWNoIHNhbXBsZSBzaXplIHRoYXQgZGV0ZXJtaW5lcyB3aGVuIGEgQ29oZW4ncyBkIHZhbHVlIGlzIGFzc29jaWF0ZWQgd2l0aCBhIHNpZ25pZmljYW50IHZzLiBub24tc2lnbmlmaWNhbnQgdC10ZXN0IHAtdmFsdWUuIFdoYXQgZGV0ZXJtaW5lcyB0aGlzIGN1dC1vZmY/IERvIHlvdSBoYXZlIGFuIGludHVpdGlvbiBmb3IgaXQ/CgojIENvaGVuJ3MgZCBhbmQgaXRzIDk1JSBDSXMgCgpUbyB1bmRlcnN0YW5kIGl0IGZ1cnRoZXIsIGxldCdzIGFkZCB0aGUgOTUlIENvbmZpZGVuY2UgSW50ZXJ2YWxzLgoKIyMgUmFuZG9tbHkgc2VsZWN0IG9uZSBkYXRhc2V0IHBlciBzYW1wbGUgc2l6ZQoKVG8gdW5kZXJzdGFuZCB0aGUgcGxvdCwgd2UnbGwgcGxvdCBqdXN0IG9uZSBkYXRhIHNldCAoaXRlcmF0aW9uKSBmb3IgZWFjaCBzYW1wbGUgc2l6ZS4KClJlLXJ1biB0aGUgY2h1bmsgdG8gc2VsZWN0IG5ldyByYW5kb20gdmFsdWVzLiBOb3RpY2UgaG93IHRoZSBtYWduaXR1ZGUgb2YgdGhlIENvaGVuJ3MgZCB2YWx1ZXMgJ2RhbmNlJyBhcm91bmQgYmV0d2VlbiBkYXRhIHNldHMgZHVlIHRvIHJhbmRvbSBzYW1wbGluZyBlcnJvciwgYnV0IHRoZSB3aWR0aCBvZiB0aGUgQ29uZmlkZW5jZSBJbnRlcnZhbHMgZG8gbm90LiBDb25maWRlbmNlIHdpZHRoIGlzIHN0ZWFkeSBhcyBpdCBpcyBhIGZ1bmN0aW9uIG9mIHNhbXBsZSBzaXplLgoKYGBge3J9CgojIHdyYW5nbGUKc2ltdWxhdGlvbiB8PgogIHVubmVzdChyZXN1bHRzKSB8PgogIG11dGF0ZShzaWduaWZpY2FudCA9IHAgPCAuMDUpIHw+CiAgIyByYW5kb21seSBzYW1wbGUgMSBlZmZlY3RzIHNpemUgcGVyIHNhbXBsZSBzaXplCiAgZ3JvdXBfYnkobl9wZXJfY29uZGl0aW9uKSB8PgogIHNsaWNlX3NhbXBsZShuID0gMSkgfD4KICB1bmdyb3VwKCkgfD4KICAjIHBsb3QKICBnZ3Bsb3QoYWVzKG5fcGVyX2NvbmRpdGlvbioyLCBjb2hlbnNfZCwgY29sb3IgPSBzaWduaWZpY2FudCkpICsKICBnZW9tX3BvaW50KCkgKwogICMgOTUlIENJcwogIGdlb21fbGluZXJhbmdlKGFlcyh5bWluID0gY29oZW5zX2RfY2lfbG93ZXIsIHltYXggPSBjb2hlbnNfZF9jaV91cHBlcikpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9ICJkb3R0ZWQiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IGJyZWFrc19wcmV0dHkobiA9IDEwKSwKICAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICJUb3RhbCBOIikgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBicmVha3NfcHJldHR5KG4gPSAxMCksCiAgICAgICAgICAgICAgICAgICAgICNsaW1pdHMgPSBjKDAsMSksCiAgICAgICAgICAgICAgICAgICAgIG5hbWUgPSAiQ29oZW4ncyBkIikgKwogIHRoZW1lX2xpbmVkcmF3KCkgKwogIHNjYWxlX2NvbG9yX3ZpcmlkaXNfZChiZWdpbiA9IDAuMywgZW5kID0gMC43KSArCiAgZ2d0aXRsZSgiUG9wdWxhdGlvbiBDb2hlbidzIGQgPSAwLjVcbk9uZSByYW5kb21seSBzZWxlY3RlZCBkYXRhc2V0IHBlciBzYW1wbGUgc2l6ZSIpCgpgYGAKCi0gU2lnbmlmaWNhbnQgd2hlbiA5NSUgQ0kgZXhjbHVkZXMgemVybyBlZmZlY3Qgc2l6ZQoKIyMgQWxsIGRhdGFzZXRzCgpOb3cgbGV0J3MgcGxvdCBhbGwgdGhlIGRhdGEgc2V0cyAoaXRlcmF0aW9ucykuCgpgYGB7ciBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MTJ9CgojIHdyYW5nbGUKc2ltdWxhdGlvbiB8PgogIHVubmVzdChyZXN1bHRzKSB8PgogIG11dGF0ZShzaWduaWZpY2FudCA9IHAgPCAuMDUsCiAgICAgICAgIHRvdGFsX24gPSBwYXN0ZSgiTiA9Iiwgbl9wZXJfY29uZGl0aW9uKjIpLAogICAgICAgICB0b3RhbF9uID0gZmN0X3Jlb3JkZXIodG90YWxfbiwgYXMubnVtZXJpYyhzdHJfZXh0cmFjdCh0b3RhbF9uLCAiXFxkKyIpKSkpIHw+CiAgIyBwbG90CiAgZ2dwbG90KGFlcyhpdGVyYXRpb24sIGNvaGVuc19kLCBjb2xvciA9IHNpZ25pZmljYW50KSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjUpICsKICBnZW9tX2xpbmVyYW5nZShhZXMoeW1pbiA9IGNvaGVuc19kX2NpX2xvd2VyLCB5bWF4ID0gY29oZW5zX2RfY2lfdXBwZXIpLCBhbHBoYSA9IDAuMikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gImRvdHRlZCIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYnJlYWtzX3ByZXR0eShuID0gMTApLAogICAgICAgICAgICAgICAgICAgICBuYW1lID0gIkl0ZXJhdGlvbiIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gYnJlYWtzX3ByZXR0eShuID0gMTApLAogICAgICAgICAgICAgICAgICAgICAjbGltaXRzID0gYygwLDEpLAogICAgICAgICAgICAgICAgICAgICBuYW1lID0gIkNvaGVuJ3MgZCIpICsKICB0aGVtZV9saW5lZHJhdygpICsKICBzY2FsZV9jb2xvcl92aXJpZGlzX2QoYmVnaW4gPSAwLjMsIGVuZCA9IDAuNykgKwogIGZhY2V0X3dyYXAofiB0b3RhbF9uLCBuY29sID0gMywgc2NhbGVzID0gImZyZWVfeSIpCgpgYGAKCiMjIE9yZGVyZWQgYnkgQ29oZW4ncyBkCgpUaGUgYWJvdmUgcGxvdCBpcyBoYXJkIHRvIHVuZGVyc3RhbmQuIExldCdzIG9yZGVyIHRoZSBDb2hlbidzIGRzIGZyb20gc21hbGxlc3QgdG8gbGFyZ2VzdCwgc28gdGhlIHNtYWxsIG9uZXMgYXJlIG9uIHRoZSBsZWZ0IGFuZCB0aGUgbGFyZ2Ugb25lcyBhcmUgb24gdGhlIHJpZ2h0LgoKYGBge3IgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTEyfQoKIyB3cmFuZ2xlCnNpbXVsYXRpb24gfD4KICB1bm5lc3QocmVzdWx0cykgfD4KICBtdXRhdGUoc2lnbmlmaWNhbnQgPSBwIDwgLjA1LAogICAgICAgICB0b3RhbF9uID0gcGFzdGUoIk4gPSIsIG5fcGVyX2NvbmRpdGlvbioyKSwKICAgICAgICAgdG90YWxfbiA9IGZjdF9yZW9yZGVyKHRvdGFsX24sIGFzLm51bWVyaWMoc3RyX2V4dHJhY3QodG90YWxfbiwgIlxcZCsiKSkpKSB8PgogIGFycmFuZ2Uobl9wZXJfY29uZGl0aW9uLCBjb2hlbnNfZCkgfD4KICBncm91cF9ieShuX3Blcl9jb25kaXRpb24pIHw+CiAgbXV0YXRlKHJhbmsgPSByb3dfbnVtYmVyKCkpIHw+CiAgdW5ncm91cCgpIHw+CiAgIyBwbG90CiAgZ2dwbG90KGFlcyhyYW5rLCBjb2hlbnNfZCwgY29sb3IgPSBzaWduaWZpY2FudCkpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fbGluZXJhbmdlKGFlcyh5bWluID0gY29oZW5zX2RfY2lfbG93ZXIsIHltYXggPSBjb2hlbnNfZF9jaV91cHBlciksIGFscGhhID0gMC4yKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAiZG90dGVkIikgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBicmVha3NfcHJldHR5KG4gPSAxMCksCiAgICAgICAgICAgICAgICAgICAgIG5hbWUgPSAiUmFua2VkIGl0ZXJhdGlvbiIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gYnJlYWtzX3ByZXR0eShuID0gMTApLAogICAgICAgICAgICAgICAgICAgICAjbGltaXRzID0gYygwLDEpLAogICAgICAgICAgICAgICAgICAgICBuYW1lID0gIkNvaGVuJ3MgZCIpICsKICB0aGVtZV9saW5lZHJhdygpICsKICBzY2FsZV9jb2xvcl92aXJpZGlzX2QoYmVnaW4gPSAwLjMsIGVuZCA9IDAuNykgKwogIGZhY2V0X3dyYXAofiB0b3RhbF9uLCBuY29sID0gMykKCmBgYAoKLSBOb3RpY2UgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIDk1JSBDSSBhbmQgcCB2YWx1ZSBzaWduaWZpY2FuY2UuCi0gQSBjZXJ0YWluIHBlcmNlbnRhZ2Ugb2YgQ29oZW4ncyBkcyBhcmUgZ3JlZW4gdnMuIGJsdWUuIFdoYXQgaXMgdGhpcyBwZXJjZW50YWdlIGFsc28gY2FsbGVkPyBXaGF0IHN0YXRpc3RpY2FsIHByb3BlcnR5PwoKIyBNZWFuIENvaGVuJ3MgZCBhbmQgbWVhbiBpbnRlcnZhbCB3aWR0aCBieSBzYW1wbGUgc2l6ZQoKTm93IGxldCdzIGF2ZXJhZ2Ugb3ZlciB0aGUgQ29oZW4ncyBkcyBpbiBlYWNoIGNvbmRpdGlvbiB0byBmaW5kIHRoZSBtZWFuIENvaGVuJ3MgZCBhbmQgaXRzIG1lYW4gOTUlIENJcy4KCmBgYHtyIGZpZy5oZWlnaHQ9Mi41LCBmaWcud2lkdGg9Nn0KCiMgd3JhbmdsZQpzaW11bGF0aW9uX3N1bW1hcnkgPC0gc2ltdWxhdGlvbiB8PgogICMgdW5uZXN0IHJlc3VsdHMKICB1bm5lc3QocmVzdWx0cykgfD4KICBncm91cF9ieShuX3Blcl9jb25kaXRpb24pIHw+CiAgc3VtbWFyaXplKHByb3BvcnRpb25fc2lnbmlmaWNhbnQgPSBtZWFuKHAgPCAuMDUpLCAKICAgICAgICAgICAgbWVhbl9jb2hlbnNfZCA9IG1lYW4oY29oZW5zX2QpLAogICAgICAgICAgICBtZWFuX2NvaGVuc19kX2NpX2xvd2VyID0gbWVhbihjb2hlbnNfZF9jaV9sb3dlciksCiAgICAgICAgICAgIG1lYW5fY29oZW5zX2RfY2lfdXBwZXIgPSBtZWFuKGNvaGVuc19kX2NpX3VwcGVyKSkgfD4KICBtdXRhdGUoY2VudGVyZWRfbWVhbl9jb2hlbnNfZF9jaV9sb3dlciA9IG1lYW5fY29oZW5zX2RfY2lfbG93ZXIgLSBtZWFuX2NvaGVuc19kLAogICAgICAgICBjZW50ZXJlZF9tZWFuX2NvaGVuc19kX2NpX3VwcGVyID0gbWVhbl9jb2hlbnNfZF9jaV91cHBlciAtIG1lYW5fY29oZW5zX2QpCgojIHBsb3QgcmVzdWx0cwpwMSA8LSBnZ3Bsb3Qoc2ltdWxhdGlvbl9zdW1tYXJ5LCBhZXMobl9wZXJfY29uZGl0aW9uKjIsIG1lYW5fY29oZW5zX2QpKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX2xpbmVyYW5nZShhZXMoeW1pbiA9IG1lYW5fY29oZW5zX2RfY2lfbG93ZXIsIHltYXggPSBtZWFuX2NvaGVuc19kX2NpX3VwcGVyKSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gImRvdHRlZCIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYnJlYWtzX3ByZXR0eShuID0gMTApLAogICAgICAgICAgICAgICAgICAgICBuYW1lID0gIlRvdGFsIHNhbXBsZSBzaXplIikgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBicmVha3NfcHJldHR5KG4gPSA1KSwKICAgICAgICAgICAgICAgICAgICAgI2xpbWl0cyA9IGMoMCwxKSwKICAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICJNZWFuIENvaGVuJ3MgZFxuKGFuZCBtZWFuIDk1JSBDSXMpIikgKwogIHRoZW1lX2xpbmVkcmF3KCkgKwogIGdndGl0bGUoIlBvcHVsYXRpb24gQ29oZW4ncyBkID0gMC41IikKCnAxCgpgYGAKCiMgTWVhbiBDb2hlbidzIGQgYW5kIHBvd2VyIGJ5IHNhbXBsZSBzaXplCgpgYGB7ciBmaWcuaGVpZ2h0PTUsIGZpZy53aWR0aD02fQoKcDIgPC0gZ2dwbG90KHNpbXVsYXRpb25fc3VtbWFyeSwgYWVzKG5fcGVyX2NvbmRpdGlvbioyLCBwcm9wb3J0aW9uX3NpZ25pZmljYW50KSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMC4wNSwgbGluZXR5cGUgPSAiZG90dGVkIikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAuODAsIGxpbmV0eXBlID0gImRvdHRlZCIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYnJlYWtzX3ByZXR0eShuID0gMTApLAogICAgICAgICAgICAgICAgICAgICBuYW1lID0gIlRvdGFsIHNhbXBsZSBzaXplIikgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBicmVha3NfcHJldHR5KG4gPSA1KSwKICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygwLDEpLAogICAgICAgICAgICAgICAgICAgICBuYW1lID0gIlByb3BvcnRpb24gb2Ygc2lnbmlmaWNhbnRcbnAtdmFsdWVzIikgKwogIHRoZW1lX2xpbmVkcmF3KCkgCgpwMSArIHAyICsgcGxvdF9sYXlvdXQobmNvbCA9IDEpCgpgYGAKCiMgRXhlcmNpc2U6IFBvd2VyIGZvciBlcXVpdmFsZW5jZSB0ZXN0CgpTZWUgTGFrZW5zIGV0IGFsLiwgMjAxOCBmb3IgYSB0dXRvcmlhbCBvbiB0aGUgY29uY2VwdHMgYmVsb3cuCgpVc2luZyBhIFNtYWxsZXN0IEVmZmVjdCBTaXplIG9mIEludGVyZXN0IChTRVNPSSkgb2YgQ29oZW4ncyBkID0gMC4yLCB3aGF0IGlzIHRoZSBwb3dlciBvZiBhIFR3byBPbmUtU2lkZWQgRXF1aXZhbGVuY2UgVGVzdCAoVE9TVCkgZm9yIGRpZmZlcmVudCBzYW1wbGUgc2l6ZXM/IFdoYXQgTiBpcyBuZWVkZWQgZm9yIDgwJSBwb3dlciB0byBkZXRlY3QgYSB0cnVlIG51bGwgZWZmZWN0IHNpemUgYXMgZXF1aXZhbGVudCB0byB6ZXJvPwoKTm90ZTogYmVjYXVzZSByZWFzb25zLCB1c2UgdGhlIDkwJSBDb25maWRlbmNlIEludGVydmFsIGluc3RlYWQgb2YgOTUgKHNlZSBMYWtlbnMgZXQgYWwuLCAyMDE4KS4KCmBgYHtyfQoKa25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIm1hdGVyaWFscy9sYWtlbnMgZXQgYWwgMjAxOCBmaWd1cmUgMS5wbmciKQoKYGBgCgojIFNlc3Npb24gaW5mbwoKYGBge3J9CgpzZXNzaW9uSW5mbygpCgpgYGAKCgo=